/*
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2024-05-27 09:04:27
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2024-08-20 15:45:00
 * @FilePath: /vue3-uniapp/src/service/useRequestManager.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/**
 * 不使用这个了，直接使用rxjs来实现依赖更新，看useRequestSubject
 */
type RequestByModelType<M> = (model?: M) => void;

type RequestInstanceKey = { name: string };

export class RequestManager<R extends Function, M> {
    /**
     * 关联request的RequestManager实例的集合
     * request为key
     * value为以RequestInstanceKey为key，以RequestManager为value的WeakMap
     */
    static instanceMaps = new WeakMap<
        Function,
        WeakMap<RequestInstanceKey, RequestManager<any, any>>
    >();
    /**
     * 关联request的RequestManager实例的集合
     * request为key
     * value为RequestInstanceKey的Set集合
     */
    static keyMaps = new WeakMap();

    key: RequestInstanceKey;

    private request: R;

    private requestByModel: RequestByModelType<M>;
    // opt { request: function, requestByModel: function }
    // opt.request保证唯一，因为这个还用于weakMap的索引
    constructor(opt: { request: R; requestByModel: RequestByModelType<M> }) {
        this.request = opt.request;
        this.requestByModel = opt.requestByModel;
        const instanceMap = RequestManager.getInstanceMap(this.request);
        const keySet = RequestManager.getKeySet(this.request);
        this.key = { name: `${Date.now()}` };
        instanceMap.set(this.key, this);
        keySet.add(this.key);
    }

    private static getInstanceMap(
        key: Function
    ): WeakMap<RequestInstanceKey, RequestManager<any, any>> {
        let instanceMap;
        if (RequestManager.instanceMaps.has(key)) {
            instanceMap = RequestManager.instanceMaps.get(key);
            if (instanceMap === undefined) {
                throw new Error(
                    '[RequestManager getInstanceMap]获取到不存在的instance'
                );
            }
        } else {
            instanceMap = new WeakMap<
                RequestInstanceKey,
                RequestManager<any, any>
            >();
            RequestManager.instanceMaps.set(key, instanceMap);
        }
        return instanceMap;
    }

    private static getKeySet(key: Function): Set<RequestInstanceKey> {
        let keySet;
        if (RequestManager.keyMaps.has(key)) {
            keySet = RequestManager.keyMaps.get(key);
        } else {
            keySet = new Set();
            RequestManager.keyMaps.set(key, keySet);
        }
        return keySet;
    }

    // 用于更新所有依赖于request的请求
    static setAll(request: Function, model = {}) {
        const instanceMap = RequestManager.getInstanceMap(request);
        const keySet = RequestManager.getKeySet(request);
        if (instanceMap && keySet) {
            keySet.forEach((key) => {
                const item = instanceMap.get(key);
                if (item === undefined) {
                    throw new Error(
                        '[RequestManager setAll]key无法获取有效实例'
                    );
                }
                item.set(model);
            });
        }
    }

    set(model: M) {
        this.requestByModel(model);
    }

    handle(...args: any[]) {
        return this.request.apply(null, args);
    }

    destroy() {
        const instanceMap = RequestManager.getInstanceMap(this.request);
        const keySet = RequestManager.getKeySet(this.request);
        instanceMap.delete(this.key);
        keySet.delete(this.key);
        console.log('清掉了');
    }
}

export const useRequestManager = <R extends Function, M>(
    request: R,
    requestByModel: RequestByModelType<M>
) => {
    const manager = new RequestManager({
        request,
        requestByModel
    });
    onBeforeUnmount(() => {
        manager.destroy();
    });
};
